package com.bruce.tool.orm.mybatis.generator.plugin;

import com.bruce.tool.orm.mybatis.generator.creater.core.BaseCreater;
import com.google.common.collect.Lists;
import org.codehaus.plexus.util.StringUtils;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;

import java.util.List;

/**
 * 功能 :
 * 1.生成service层业务服务类
 * 2.自动注入mapper
 * 3.自动注入domain
 * @author : Bruce(刘正航) 6:50 下午 2020/1/4
 */
public class ServiceClassPlugin extends BaseCreater {

    private String filePath;
    private String serviceSuffix = "Service";
    private String servicePackage;
    private String mapperPackage;

    /**包引入**/
    private final List<String> annotations = Lists.newArrayList("@Component");
    private final List<String> imports = Lists.newArrayList(
            "com.bruce.tool.orm.mybatis.core.mapper.BaseMapper",
            "com.bruce.tool.orm.mybatis.core.service.AbstractBaseService",
            "org.springframework.beans.factory.annotation.Autowired",
            "org.springframework.stereotype.Component"
    );
    private final String superClass = "com.bruce.tool.orm.mybatis.core.service.AbstractBaseService";

    @Override
    public boolean validate(List<String> warnings) {
        filePath = super.getProperties().getProperty("service.path");
        serviceSuffix = super.getProperties().getProperty("service.suffix");
        servicePackage = super.getProperties().getProperty("service.package");
        mapperPackage = super.getProperties().getProperty("xmlmapper.package");
        return true;
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        if(StringUtils.isBlank(filePath) || StringUtils.isBlank(servicePackage)){
            return true;
        }
        FullyQualifiedJavaType domainType = topLevelClass.getType();
        String serviceName = domainType.getShortName() + serviceSuffix;
        String serviceImplName = domainType.getShortName() + serviceSuffix + "Impl";
        String mapperName = domainType.getShortName() + "Mapper";
        String mapperFieldName = lowerCaseFirstLetter(domainType.getShortName()) + "Mapper";
        TopLevelClass dubboServiceImpl = new TopLevelClass(new FullyQualifiedJavaType(servicePackage+"."+serviceImplName));
        dubboServiceImpl.setVisibility(JavaVisibility.PUBLIC);

        FullyQualifiedJavaType supperClass = new FullyQualifiedJavaType(superClass);
        supperClass.addTypeArgument(new FullyQualifiedJavaType(domainType.getShortName()));
        dubboServiceImpl.setSuperClass(supperClass);

        dubboServiceImpl.addSuperInterface(new FullyQualifiedJavaType(serviceName));

        for (String needImport : imports) {
            dubboServiceImpl.addImportedType(new FullyQualifiedJavaType(needImport));
        }
        dubboServiceImpl.addImportedType(domainType);
        dubboServiceImpl.addImportedType(mapperPackage+"."+mapperName);

        for (String annotation : annotations) {
            dubboServiceImpl.addAnnotation(annotation);
        }

        Field field = new Field(mapperFieldName,new FullyQualifiedJavaType(mapperName));
        field.setVisibility(JavaVisibility.PRIVATE);
        field.addJavaDocLine("@Autowired");
        dubboServiceImpl.addField(field);

        Method clazz = new Method("clazz");
        clazz.setVisibility(JavaVisibility.PROTECTED);
        clazz.setReturnType(new FullyQualifiedJavaType("Class<"+domainType.getShortName()+">"));
        clazz.addBodyLine("return "+domainType.getShortName()+".class;");
        clazz.addJavaDocLine("@Override");
        dubboServiceImpl.addMethod(clazz);

        Method baseMapper = new Method("baseMapper");
        baseMapper.setVisibility(JavaVisibility.PROTECTED);
        baseMapper.setReturnType(new FullyQualifiedJavaType("BaseMapper<"+domainType.getShortName()+">"));
        baseMapper.addBodyLine("return "+mapperFieldName+";");
        baseMapper.addJavaDocLine("@Override");
        dubboServiceImpl.addMethod(baseMapper);
        createClassFile(filePath, dubboServiceImpl);

        return true;
    }

    /**第一个字母小写**/
    private String lowerCaseFirstLetter(String source) {
        char[] chars = source.toCharArray();
        if (chars[0] >= 'A' && chars[0] <= 'Z') {
            chars[0] = (char)(chars[0] + 32);
        }
        return new String(chars);
    }
}
